package com.universe.titan.common.util;

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import org.apache.commons.codec.binary.Base64;

import java.security.KeyPair;
import java.util.Objects;


public class RSAUtil {

    private static final TimedCache<String, RSA> CACHE = CacheUtil.newTimedCache(30000);

    static {
        CACHE.schedulePrune(30000);
    }

    /**
     * 私钥解密
     *
     * @param str 加密后的字符串
     * @return
     */
    public static String decrypt(String str, String publicKey, String privateKey) {
        String key = SecureUtil.md5(privateKey + "|||" + publicKey);
        if (Objects.isNull(CACHE.get(key))) {
            CACHE.put(key, SecureUtil.rsa(SecureUtil.decode(privateKey), SecureUtil.decode(publicKey)));
        }
        return decrypt(str, SecureUtil.decode(publicKey), SecureUtil.decode(privateKey), CACHE.get(key));

    }

    private static String decrypt(String str, byte[] publicKey, byte[] privateKey, RSA ras) {
        if (Objects.nonNull(ras)) {
            return ras.decryptStr(str, KeyType.PrivateKey);
        }
        return SecureUtil.rsa(privateKey, publicKey).decryptStr(str, KeyType.PrivateKey);
    }

    public static void main(String[] args) {
//        内容
        String content = "你好啊啊啊啊,AAAA,123,ad,hahaha哈哈哈";
//        公钥私钥自动生成
        KeyPair pair = SecureUtil.generateKeyPair("RSA");

//        用哪套公钥私钥都行 2选1
//            第一套公钥私钥 Base64形式的公钥私钥
        String publicKey = new String(Base64.encodeBase64(pair.getPublic().getEncoded()));
        String privateKey= new String(Base64.encodeBase64((pair.getPrivate().getEncoded())));

//            第二套公钥私钥 hex形式的公钥私钥
//        String publicKey = HexUtil.encodeHexStr(pair.getPublic().getEncoded());
//        String privateKey = HexUtil.encodeHexStr(pair.getPrivate().getEncoded());

        //        hex或者base64加密都行
//           1.如果是base64的公钥私钥 则用此传参加密(hex或者base64加密都行)
//        String encryptStr = SecureUtil.rsa(privateKey, publicKey).encryptBase64(content, KeyType.PublicKey);
//        String encryptStr = SecureUtil.rsa(privateKey, publicKey).encryptHex(content, KeyType.PublicKey);


//          2.如果是hex的公钥私钥 则用此传参加密(hex或者base64加密都行)
//        String encryptStr  = SecureUtil.rsa(SecureUtil.decode(privateKey), SecureUtil.decode(publicKey)).encryptBase64(content, KeyType.PublicKey);
        String encryptStr = SecureUtil.rsa(SecureUtil.decode(privateKey), SecureUtil.decode(publicKey)).encryptHex(content, KeyType.PublicKey);


//          解密hex或者base64的加密数据都行
        String resultStr = decrypt(encryptStr, publicKey, privateKey);


        System.out.println(String.format("原内容:%s,加密后内容:%s,解密后内容:%s", content, encryptStr, resultStr));
        System.out.println("私钥:" + privateKey);
        System.out.println("公钥:" + publicKey);

    }
}
